<template>
	<view v-if="visible" class="popup-wrapper" @touchmove.stop.prevent="() => {}" ref="mypopupRef">
		<!-- 遮罩层 -->
		<view class="popup-mask" :class="{ 'popup-mask-show': showMask }" @click="handleMaskClick"></view>

		<!-- 弹窗内容 -->
		<view class="popup-container" :class="[
        `popup-${type}`,
        `popup-animation-${animation}`,
        { 'popup-show': isShow }
      ]" :style="containerStyle">
			<slot></slot>

			<!-- 关闭按钮 -->
			<view v-if="showClose" class="popup-close" @click="close">
				<text class="close-icon">✕</text>
			</view>
		</view>
	</view>
</template>

<script setup lang="ts">
	import { ref, computed, watch, onMounted, nextTick } from 'vue'

	// 定义 props
	interface Props {
		modelValue ?: boolean
		type ?: 'center' | 'top' | 'bottom' | 'left' | 'right'
		animation ?: 'fade' | 'slide' | 'zoom'
		showMask ?: boolean
		maskClosable ?: boolean
		showClose ?: boolean
		borderRadius ?: string
		backgroundColor ?: string
		zIndex ?: number
	}

	const props = withDefaults(defineProps<Props>(), {
		modelValue: false,
		type: 'center',
		animation: 'fade',
		showMask: true,
		maskClosable: true,
		showClose: false,
		borderRadius: '10rpx',
		backgroundColor: '#ffffff',
		zIndex: 999
	})

	// 定义 emits
	const emit = defineEmits<{
		(e : 'update:modelValue', value : boolean) : void
		(e : 'open') : void
		(e : 'close') : void
	}>()

	// 响应式数据
	const visible = ref(false)
	const isShow = ref(false)

	// 计算容器样式
	const containerStyle = computed(() => {
		return {
			'border-radius': props.borderRadius,
			'background-color': props.backgroundColor,
			'z-index': props.zIndex + 1
		}
	})

	// 打开弹窗
	const open = () => {
		visible.value = true
		nextTick(() => {
			setTimeout(() => {
				isShow.value = true
			}, 30)
		})
		emit('open')
	}

	// 关闭弹窗
	const close = () => {
		isShow.value = false
		setTimeout(() => {
			visible.value = false
			emit('update:modelValue', false)
			emit('close')
		}, 300)
	}

	// 处理遮罩点击
	const handleMaskClick = () => {
		if (props.maskClosable) {
			close()
		}
	}

	// 监听 modelValue 变化
	watch(() => props.modelValue, (newVal) => {
		if (newVal) {
			open()
		} else {
			close()
		}
	}, { immediate: true })

	const mypopupRef = ref()
	// 暴露方法给父组件
	defineExpose({
		open,
		close,
		mypopupRef
	})

	onMounted(() => {
		if (props.modelValue) {
			open()
		}
	})
</script>

<style scoped>
	.popup-wrapper {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		width: 100%;
		height: 100%;
		z-index: 999;
	}

	.popup-mask {
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		background-color: rgba(0, 0, 0, 0);
		transition: background-color 0.3s ease;
	}

	.popup-mask-show {
		background-color: rgba(0, 0, 0, 0.4);
	}

	.popup-container {
		position: absolute;
		background-color: #ffffff;
		transition: all 0.3s ease;
		opacity: 0;
	}

	.popup-show {
		opacity: 1;
	}

	/* 动画类型 */
	.popup-animation-fade {
		transition: opacity 0.3s ease;
	}

	.popup-animation-slide {
		transition: all 0.3s ease;
	}

	.popup-animation-zoom {
		transform: scale(0.8);
		transition: all 0.3s ease;
	}

	.popup-show.popup-animation-zoom {
		transform: scale(1);
	}

	/* 弹窗位置 */
	.popup-center {
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%) scale(0.8);
	}

	.popup-show.popup-center {
		transform: translate(-50%, -50%) scale(1);
	}

	.popup-top {
		top: 0;
		left: 0;
		right: 0;
		transform: translateY(-100%);
	}

	.popup-show.popup-top {
		transform: translateY(0);
	}

	.popup-bottom {
		bottom: 0;
		left: 0;
		right: 0;
		transform: translateY(100%);
	}

	.popup-show.popup-bottom {
		transform: translateY(0);
	}

	.popup-left {
		top: 0;
		left: 0;
		bottom: 0;
		transform: translateX(-100%);
	}

	.popup-show.popup-left {
		transform: translateX(0);
	}

	.popup-right {
		top: 0;
		right: 0;
		bottom: 0;
		transform: translateX(100%);
	}

	.popup-show.popup-right {
		transform: translateX(0);
	}

	/* 关闭按钮 */
	.popup-close {
		position: absolute;
		top: 20rpx;
		right: 20rpx;
		width: 40rpx;
		height: 40rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		z-index: 1000;
	}

	.close-icon {
		font-size: 32rpx;
		color: #999;
	}
</style>